import React, { useState } from 'react';
import {
  Table,
  Input,
  InputNumber,
  Popconfirm,
  Form,
  Typography,
  Button,
  Radio,
  Select,
  Divider,
} from 'antd';
import {
  sortableContainer,
  sortableElement,
  sortableHandle,
} from 'react-sortable-hoc';
import { MenuOutlined } from '@ant-design/icons';
import { arrayMoveImmutable } from 'array-move';
import './index.less';

const selectData = [
  {
    label: 'jack',
    value: 'jack',
  },
  {
    label: 'lucy',
    value: 'lucy',
  },
  {
    label: 'mark',
    value: 'mark',
  },
];
const originData = [
  {
    key: '1',
    name: 'jack',
    age: 32,
    address: 'New York No. 1 Lake Park',
    index: 0,
    major: 0,
  },
  {
    key: '2',
    name: 'lucy',
    age: 42,
    address: 'London No. 1 Lake Park',
    index: 1,
    major: 1,
  },
  {
    key: '3',
    name: 'mark',
    age: 32,
    address: 'Sidney No. 1 Lake Park',
    index: 2,
    major: 0,
  },
];

/**
 * 根据inputType 显示相应的数据类型
 * @param {*} inputType
 * @returns
 */
const getInputNode = (inputType) => {
  switch (inputType) {
    case 'select':
      return (
        <Select
          options={selectData}
          placeholder="请选择"
          onChange={(value) => {
            console.log('value', value);
          }}
        />
      );
    case 'number':
      return <InputNumber />;
    case 'input':
      return <Input />;
    case 'radio':
      return (
        <Radio.Group>
          <Radio value={0}>是</Radio>
          <Radio value={1}>否</Radio>
        </Radio.Group>
      );
    default:
      break;
  }
};

const getRule = (inputType, title) => {
  switch (inputType) {
    case 'select':
      return '请选择';
    case 'radio':
      break;
    default:
      return `请输入${title}`;
  }
};

const EditableCell = ({
  editing,
  dataIndex,
  title,
  inputType,
  record,
  index,
  children,
  ...restProps
}) => {
  // const inputNode = inputType === 'number' ? <InputNumber /> : <Input />;
  const inputNode = getInputNode(inputType);
  return (
    <td {...restProps}>
      {editing ? (
        <Form.Item
          name={dataIndex}
          style={{
            margin: 0,
          }}
          rules={[
            {
              required: true,
              message: getRule(inputType, title),
            },
          ]}
        >
          {inputNode}
        </Form.Item>
      ) : (
        children
      )}
    </td>
  );
};

const EditableTable = () => {
  const [form] = Form.useForm();
  const [data, setData] = useState(originData);
  const [editingKey, setEditingKey] = useState('');

  const isEditing = (record) => record.key === editingKey;

  const edit = (record) => {
    form.setFieldsValue({
      name: '',
      age: '',
      address: '',
      ...record,
    });
    setEditingKey(record.key);
  };

  const cancel = () => {
    setEditingKey('');
  };

  const save = async (key) => {
    try {
      const row = await form.validateFields();
      const newData = [...data];
      const index = newData.findIndex((item) => key === item.key);

      if (index > -1) {
        const item = newData[index];
        newData.splice(index, 1, { ...item, ...row });
        setData(newData);
        setEditingKey('');
      } else {
        newData.push(row);
        setData(newData);
        setEditingKey('');
      }
    } catch (errInfo) {
      console.log('Validate Failed:', errInfo);
    }
  };

  const DragHandle = sortableHandle(() => (
    <MenuOutlined style={{ cursor: 'grab', color: '#999' }} />
  ));

  const columns = [
    {
      title: '排序',
      dataIndex: 'sort',
      width: '10%',
      editable: false,
      render: (_, row) => `第${row.index + 1}列`,
    },
    {
      title: 'name',
      dataIndex: 'name',
      width: '15%',
      editable: true,
      inputType: 'select',
    },
    {
      title: 'age',
      dataIndex: 'age',
      width: '5%',
      editable: true,
      inputType: 'number',
    },
    {
      title: 'address',
      dataIndex: 'address',
      width: '30%',
      editable: true,
      inputType: 'input',
    },
    {
      title: 'major',
      dataIndex: 'major',
      width: '20%',
      editable: true,
      inputType: 'radio',
      render: (_) => (_ == 0 ? '是' : '否'),
    },
    {
      title: '操作',
      dataIndex: 'operation',
      render: (_, record) => {
        const editable = isEditing(record);
        return editable ? (
          <span>
            <a
              href="javascript:;"
              onClick={() => save(record.key)}
              style={{
                marginRight: 8,
              }}
            >
              保存
            </a>
            <Popconfirm title="Sure to cancel?" onConfirm={cancel}>
              <a>取消</a>
            </Popconfirm>
          </span>
        ) : (
          <>
            <Typography.Link
              disabled={editingKey !== ''}
              onClick={() => edit(record)}
            >
              编辑
            </Typography.Link>
            <Divider type="vertical" />
            <DragHandle />
          </>
        );
      },
    },
    // {
    //   title: 'Sort',
    //   dataIndex: 'sort',
    //   width: 30,
    //   className: 'drag-visible',
    //   render: () => <DragHandle />,
    // },
  ];
  const mergedColumns = columns.map((col) => {
    if (!col.editable) {
      return col;
    }

    return {
      ...col,
      onCell: (record) => ({
        record,
        inputType: col.inputType,
        dataIndex: col.dataIndex,
        title: col.title,
        editing: isEditing(record),
      }),
    };
  });

  const SortableItem = sortableElement((props) => <tr {...props} />);
  const SortableContainer = sortableContainer((props) => <tbody {...props} />);

  const onSortEnd = ({ oldIndex, newIndex }) => {
    if (oldIndex !== newIndex) {
      const newData = arrayMoveImmutable(
        [].concat(data),
        oldIndex,
        newIndex
      ).filter((el) => !!el);
      setData(newData);
    }
  };

  const DraggableContainer = (props) => (
    <SortableContainer
      useDragHandle
      disableAutoscroll
      helperClass="row-dragging"
      onSortEnd={onSortEnd}
      {...props}
    />
  );

  const handleAdd = () => {
    const newData = {
      name: '',
      age: '',
      address: '',
      major: 0,
      index: data.length,
    };
    const arr = [...data];
    arr.push(newData);
    setData([...arr]);
  };

  const DraggableBodyRow = ({ className, style, ...restProps }) => {
    // function findIndex base on Table rowKey props and should always be a right array index
    const index = data.findIndex((x) => x.index === restProps['data-row-key']);
    return <SortableItem index={index} {...restProps} />;
  };

  const onSubmit = () => {
    console.log('form', form.getFieldsValue(true));
    console.log('data', data);
  };

  return (
    <Form form={form} component={false}>
      <div style={{ margin: 20 }}>
        <Button onClick={handleAdd}>添加一行</Button>
      </div>
      <Table
        rowKey="index"
        components={{
          body: {
            cell: EditableCell,
            wrapper: DraggableContainer,
            row: DraggableBodyRow,
          },
        }}
        bordered
        dataSource={data}
        columns={mergedColumns}
        rowClassName="editable-row"
        pagination={{
          onChange: cancel,
        }}
      />
      <Button onClick={onSubmit}>submit</Button>
    </Form>
  );
};
export default EditableTable;
